using Godot;
using System;
using CurrentGame.Utils.Interpolation;

namespace CurrentGame.GUI.PlaceGrid;


public partial class SelectBox : Sprite2D
{
	[Export]
	public PlaceModeGrid Grid { get; set; }
	[Export]
	public Marker2D Anchor { get; set; }

	[ExportGroup("Animation settings")]
	[Export]
	public float SelectedScale { get; set; } = 0.9f;
	[Export]
	public float UnavailableModulate { get; set; } = 0.5f;
	[Export]
	public float UnavailableAlpha { get; set; } = 0.5f;
	[Export]
	public float AvailableModulate { get; set; } = 1.0f;
	[Export]
	public float TransformInterpolationWeight
	{
		get => _lerpTransform.Weight;
		set => _lerpTransform.Weight = value;
	}
	[Export]
	public float ColorInterpolationWeight
	{
		get => _lerpColor.Weight;
		set => _lerpColor.Weight = value;
	}

	// private members
	private float _savedScale;
	private bool _disabling = false;
	private LerpInterpolation _lerpColor, _lerpTransform;

	public SelectBox()
	{
		_lerpColor = new LerpInterpolation(0.01f, new Vector3(-1f, 0.00001f, -1f))
		{
			Vector2Value = new Vector2(0.0f, 1.0f)
		};
		_lerpColor.Teleport();

		_lerpTransform = new LerpInterpolation(0.01f, new Vector3(-1f, -1f, 0.0001f))
		{
			Vector3Value = new Vector3(0.0f, 0.0f, 1.0f)
		};
		_lerpTransform.Teleport();
	}

	// GODOT - Callbacks
	public override void _Ready()
	{
		Grid.SelectGridChanged += Signal_OnSelectionChanged;
		Grid.EnableStateChanged += Signal_OnSelectionEnabled;
		_lerpColor.ReachStableValue += Signal_ColorInterpolationStable;
		_savedScale = Scale.X;
	}

    public override void _Process(double delta)
    {
        if (_lerpTransform.Process(delta) || _lerpColor.Process(delta))
		{
			var currentColor = _lerpColor.Vector2Value;			// alpha, gray
			var currentTransform = _lerpTransform.Vector3Value; // x, y, scale

			var modulate = new Color(currentColor.Y, currentColor.Y, currentColor.Y, currentColor.X);
			var position = new Vector2(currentTransform.X, currentTransform.Y);

			GlobalPosition = position;
			Modulate = modulate;
			Scale = new Vector2(currentTransform.Z, currentTransform.Z);
		}
    }

	// GODOT - Signals
	private void Signal_OnSelectionChanged(Vector2I grid, Vector2 position, bool available)
	{
		// Update position & scale
		float scale = _savedScale;
		if (available) scale = SelectedScale;

		_lerpTransform.Vector3Value = new Vector3(position.X, position.Y, scale);

		// Update color
		float alpha = UnavailableAlpha, modulate = UnavailableModulate;
		if (available)
		{
			alpha = 1.0f;
			modulate = AvailableModulate;
		}
		_lerpColor.Vector2Value = new Vector2(alpha, modulate);
	}

	private void Signal_OnSelectionEnabled(bool enabled)
	{
		if (enabled)
		{
			Visible = true;
			_lerpColor.Vector2Value = new Vector2(UnavailableAlpha, UnavailableModulate);
        }
		else
		{
			_disabling = true;
			_lerpColor.Vector2Value = new Vector2(0.0f, UnavailableModulate);
		}
	}

	// NOT GODOT - Signals
	private void Signal_ColorInterpolationStable(float v, Vector2 v2, Vector3 v3)
	{
		if (v2.X <= 0.0f && _disabling)
		{
			Visible = false;
			_disabling = false;
		}
	}
}
